package cn.wen.mybatis.framework.executor.resultset;import cn.wen.mybatis.framework.annotations.AutomapConstructor;import cn.wen.mybatis.framework.binding.MapperMethod;import cn.wen.mybatis.framework.cache.CacheKey;import cn.wen.mybatis.framework.executor.ErrorContext;import cn.wen.mybatis.framework.executor.Executor;import cn.wen.mybatis.framework.executor.ExecutorException;import cn.wen.mybatis.framework.executor.loader.ResultLoader;import cn.wen.mybatis.framework.executor.loader.ResultLoaderMap;import cn.wen.mybatis.framework.executor.paramete.ParameterHandler;import cn.wen.mybatis.framework.executor.result.DefaultResultContext;import cn.wen.mybatis.framework.executor.result.DefaultResultHandler;import cn.wen.mybatis.framework.executor.result.ResultMapException;import cn.wen.mybatis.framework.mapping.*;import cn.wen.mybatis.framework.reflection.MetaClass;import cn.wen.mybatis.framework.reflection.MetaObject;import cn.wen.mybatis.framework.reflection.ReflectorFactory;import cn.wen.mybatis.framework.reflection.factory.ObjectFactory;import cn.wen.mybatis.framework.session.*;import cn.wen.mybatis.framework.type.JdbcType;import cn.wen.mybatis.framework.type.TypeHandler;import cn.wen.mybatis.framework.type.TypeHandlerRegistry;import java.lang.reflect.Constructor;import java.sql.CallableStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.*;/** * 处理结果集的默认类 * Mapper.xml的resultMap标签信息封装类对象 简称 resultMap标签对象 * 根据resultMap对象与结果集构建出来的java类型对象，简称为 结果对象 */public class DefaultResultSetHandler implements ResultSetHandler {    /**     * 标记着待定的对象     */    private static final Object DEFERRED = new Object();    // 执行器    private final Executor executor;    // mybatis的全局配置信息    private final Configuration configuration;    // Mapper.xml文件的select、delete、update、insert这些DML标签的封装类    private final MappedStatement mappedStatement;    // Mybatis的分页对象    private final RowBounds rowBounds;    // 参数处理器    private final ParameterHandler parameterHandler;    // 结果处理器    private final ResultHandler<?> resultHandler;    // 参数映射与可执行SQL封装类对象    private final BoundSql boundSql;    // 类型处理器注册器对象    private final TypeHandlerRegistry typeHandlerRegistry;    // 对象工厂，从mybatis全局配置信息中获取    private final ObjectFactory objectFactory;    // 反射工厂 从mybatis全局配置信息获取    private final ReflectorFactory reflectorFactory;    // nested resultmaps    /**     * key=缓存Key,value=嵌套的结果对象     */    private final Map<CacheKey, Object> nestedResultObjects = new HashMap<>();    private final Map<String, Object> ancestorObjects = new HashMap<>();    /**     * 上一次嵌套的resultMap对象所构建出来的对象     */    private Object previousRowValue;    // multiple resultsets    private final Map<String, ResultMapping> nextResultMaps = new HashMap<>();    private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<>();    // Cached Automappings    /**     * 上一次嵌套的resultMap对象所构建出来的对象     */    private final Map<String, List<UnMappedColumnAutoMapping>> autoMappingsCache = new HashMap<>();    // temporary marking flag that indicate using constructor mapping (use field to    // reduce memory usage)    // 表明使用构造函数映射关系的临时标志标记（使用成员变量来减少内存开销)    /**     * 当前结果对象是否使用了非无参构造函数进行构建的标记     */    private boolean useConstructorMappings;    public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql, RowBounds rowBounds) {        this.executor = executor;        this.configuration = mappedStatement.getConfiguration();        this.mappedStatement = mappedStatement;        this.rowBounds = rowBounds;        this.parameterHandler = parameterHandler;        this.boundSql = boundSql;        this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();        this.objectFactory = configuration.getObjectFactory();        this.reflectorFactory = configuration.getReflectorFactory();        this.resultHandler = resultHandler;    }    private static class UnMappedColumnAutoMapping {        /**         * 字段名         */        private final String column;        /**         * 属性名         */        private final String property;        /**         * TypeHandler 处理器         */        private final TypeHandler<?> typeHandler;        /**         * 是否为基本属性         */        private final boolean primitive;        /**         * @param column      字段名         * @param property    属性名         * @param typeHandler TypeHandler 处理器         * @param primitive   是否为基本属性         */        public UnMappedColumnAutoMapping(String column, String property, TypeHandler<?> typeHandler, boolean primitive) {            this.column = column;            this.property = property;            this.typeHandler = typeHandler;            this.primitive = primitive;        }    }    /**     * 待定关系     */    private static class PendingRelation {        /**         * 元对象         */        public MetaObject metaObject;        /**         * 结果映射         */        public ResultMapping propertyMapping;    }    /**     * 返回集参数设置 处理 {@code stmt} 中的所有结果集，返回结果对象集合     *     * @param stmt     * @return     * @throws SQLException     */    @Override    public List<Object> handleResultSets(Statement stmt) throws SQLException {        // 设置日志的上下文        ErrorContext.instance() .activity("handling results").object(mappedStatement.getId());        // <select> 标签的ResultMap属性，可以指定多个值，多个值之间用(,)分隔        final List<Object> multipleResults = new ArrayList<>();        // 初始化结果集数量为0        int resultSetCount = 0;        // 这里是获取第一个结果集，将传统JDBC的ResultSet包装成一个包含结果列元信息的ResultSetWrapper对象        ResultSetWrapper rsw = getFirstResultSet(stmt);        // 获得ResultMap 即查询结果的转换关系        List<ResultMap> resultMaps = mappedStatement.getResultMaps();        int resultMapCount = resultMaps.size();        // 验证ResultMap标签对象数量,如果rsw不为null且ResultMapCount小于1，就会抛出异常        validateResultMapsCount(rsw, resultMapCount);        // 遍历多个查询结果集  一般只有一个  重复调用的是存储过程        // 如果结果集包装类对象不为null 且 配置的ResultMap标签对象数量大于结果集数量        while (rsw != null && resultMapCount > resultSetCount) {            // 获取当前结果集对应的ResultMap            ResultMap resultMap = resultMaps.get(resultSetCount);            /**             * 构建出来的结果对象,如果父级结果属性映射不为null，会将结果对象赋值到父级结果属性对应的结果对象中，             * 否则将结果对象加入到resultHandler中。最后从resultHandler中取的最终的结果对象加入到多个结果             * 对象集合中             */            // 转换结果集，并且添加到multipleResults中 根据resultMap处理rsw生成java对象            handleResultSet(rsw, resultMap, multipleResults, null);            // 获取下一个查询结果集            rsw = getNextResultSet(stmt);            // 清空嵌套resultMap            cleanUpAfterHandlingResultSet();            // 每处理完一次，结果集数量+1            resultSetCount++;        }        // resultSets是针对多结果集的情况下，给每个结果集一个名称，多个名称之间使用,分割        String[] resultSets = mappedStatement.getResultSets();        // 如果结果集不为null        if (resultSets != null) {            // 如果结果包装对象不为null 而且 结果集数量小于配置的结果集名数量            while (rsw != null && resultSetCount < resultSets.length) {                ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);                if (parentMapping != null) {                    String nestedResultMapId = parentMapping.getNestedResultMapId();                    ResultMap resultMap = configuration.getResultMap(nestedResultMapId);                    // 一样的调用  这里只是对多个结果集进行处理                    handleResultSet(rsw, resultMap, null, parentMapping);                }                // 获取下一个结果集                rsw = getNextResultSet(stmt);                cleanUpAfterHandlingResultSet();                resultSetCount++;            }        }        // 如果multipleResults只有一个元素，只会返回该元素对象；否则返回multipleResult        return collapseSingleResultList(multipleResults);    }    //当list长度为1，表示该list的元素就是list类型的，返回元素即可。    private List<Object> collapseSingleResultList(List<Object> multipleResults) {        return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;    }    private void cleanUpAfterHandlingResultSet() {        nestedResultObjects.clear();    }    private ResultSetWrapper getNextResultSet(Statement stmt) {        // 使用这个方法能增强对JDBC驱动的容错率        try {            // 检索这个数据库是否支持从一个单一调用方法执行获得多个结果集对象            if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) {                // 疯狂的标准JDBC确定是否有更多结果的方法                // !stmt.getMoreResults() && stmt.getUpdateCount() == -1：表示已经没有更多结果                // 如果有更多结果                if (!(!stmt.getMoreResults() && stmt.getUpdateCount() == -1)) {                    // 获取结果集                    ResultSet rs = stmt.getResultSet();                    // 如果结果集对象不为null                    if (rs == null) {                        // 递归尝试重新获取下个一个结果集                        return getNextResultSet(stmt);                    } else {                        // 将结果集对象包装起来返回                        return new ResultSetWrapper(rs, configuration);                    }                }            }        } catch (Exception e) {            // Intentionally ignored.        }        return null;    }    /**     * 构建出来的结果对象,如果父级结果属性映射不为null，会将结果对象赋值到父级结果属性对应的结果对象中，     *  否则将结果对象加入到resultHandler中。最后从resultHandler中取的最终的结果对象加入到多个结果     *  对象集合中     * @param rsw 结果集包装对象     * @param resultMap resultMap标签对象     * @param multipleResults 多个结果对象集合     * @param parentMapping 父级结果属性映射     * @throws SQLException     */    private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) {        try {            // 如果 父级结果属性映射不为null            if (parentMapping != null) {                /**                 * 构建出来的结果对象,如果父级结果属性映射不为null，会将结果对象赋值到父级结果属性对应的结果对象中，                 * 否则将结果对象加入到resultHandler中                 */                //这里因为parentMapping已经确定不为null了，所以resultHandler传入null也不会有问题。                handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);            } else {                // 第一次一般来说resultHandler为空  则创建DefaultResultHandler 来处理                if (resultHandler == null) {                    // 如果用户没有指定对结果的处理器ResultHandler，那么默认会使用DefaultResultHandler                    DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);                    // 对结果集进行转换                    handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);                    // 将解析后的结果添加到multiResults中                    // 如果没有指定ResultHandler，那么默认会将解析之后的结果添加到multipleResults中                    multipleResults.add(defaultResultHandler.getResultList());                } else {                    // 用户定义了对结果集的处理方法，即ResultHandler                    // 那么使用ResultSetHandler处理之后，会将结果再交给ResultHandler进行处理                    handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);                }            }        } catch (SQLException throwables) {            throwables.printStackTrace();        }    }    /**     * 构建出来的结果对象,如果父级结果属性映射不为null，会将结果对象赋值到父级结果属性对应的结果对象中，     * 否则将结果对象加入到resultHandler中     * @param rsw 结果集包装类对象     * @param resultMap resultMap标签信息封装类对象     * @param resultHandler 一般为 {@link DefaultResultHandler} 实例     * @param rowBounds mybatis的分页     * @param parentMapping 父级结果属性映射     */    // 分成嵌套和不嵌套两种方法，进行处理，这里我们只管理不嵌套的处理，嵌套的虽然会比不嵌套复杂一点，但总体类似，差别并不大    public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {        // 判断是否有嵌套的映射        if (resultMap.hasNestedResultMaps()) {            ensureNoRowBounds();            checkResultHandler();            // 处理嵌套映射            // handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);        } else {            // 根据结果集包装类对象和简单的ResultMap标签对象，构建成结果对象并加入到resultHandler中            // 简单的结果集映射            handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);        }    }    /**     * 根据结果集包装类对象和简单的ResultMap标签对象，构建成结果对象     * @param rsw 结果集包装类对象     * @param resultMap ResultMap标签对象     * @param resultHandler 结果处理器     * @param rowBounds Mybatis的分页对象     * @param parentMapping 父级属性结果映射     * @throws SQLException     */    private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)            throws SQLException {        // ResultContext用来存放结果对象 默认结果上下文        DefaultResultContext<Object> resultContext = new DefaultResultContext<>();        // 获取jdbc查询结果集        ResultSet resultSet = rsw.getResultSet();        // 取出rowBounds中的offset，跳过结果集中的前面offset行        skipRows(resultSet, rowBounds);        // 判断是否需要接着处理，shouldProcessMoreRows判断当前处理的行数是否已经超过了rowBounds中limit指定的行数        while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {            // 根据discriminate找到适合的ResultMap            // 逐层解析resultMap鉴别器，取得最终的ResultMap标签对象            ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);            // 根据rsw 和resultMap 构建出 {@link ResultMap#getType()} 类型的对象            Object rowValue = getRowValue(rsw, discriminatedResultMap, null);            /**             * 保存对象,如果parentMapping 不为null,就将结果对象添加到parentMapping             * 的metaObject中;否则，调用结果处理器，将结果对象添加到结果处理器中             */            storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);        }    }    private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {        if (parentMapping != null) {            linkToParents(rs, parentMapping, rowValue);        } else {            callResultHandler(resultHandler, resultContext, rowValue);        }    }    /**     * 将嵌套对象记录到外层元对象相应的属性中     * @param rs 结果集     * @param parentMapping 结果映射     * @param rowValue 上一次嵌套的resultMap对象所构建出来的对象     */    private void linkToParents(ResultSet rs, ResultMapping parentMapping, Object rowValue) throws SQLException {        // 将外键对应结果集中的对象以及嵌套列名绑定到CacheKey对象中        CacheKey parentKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getForeignColumn());        // 获取该CacheKey对象对应的PendingRelation列表        List<PendingRelation> parents = pendingRelations.get(parentKey);        // 如果该列表不为null        if (parents != null) {            // 遍历PendingRelation列表            for (PendingRelation parent : parents) {                // 如果列表中的每一项不为null 且 上一次嵌套的resultMap对象所构建出来的对象也不为null                if (parent != null && rowValue != null) {                    /**                     * 上一次嵌套的resultMap对象所构建出来的对象放入元数据类型对象的相应属性中，如果为集合                     * 则在集合属性中添加该rowValue;如果不为集合，则直接将该属性设置为rowValue                     */                    linkObjects(parent.metaObject, parent.propertyMapping, rowValue);                }            }        }    }    /**     * 上一次嵌套的resultMap对象所构建出来的对象放入元数据类型对象的相应属性中，如果为集合     * 则在集合属性中添加该rowValue;如果不为集合，则直接将该属性设置为rowValue     */    private void linkObjects(MetaObject metaObject, ResultMapping resultMapping, Object rowValue) {        final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);        if (collectionProperty != null) {            final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);            targetMetaObject.add(rowValue);        } else {            // 设置嵌套对象            metaObject.setValue(resultMapping.getProperty(), rowValue);        }    }    private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMapping, MetaObject metaObject) {        final String propertyName = resultMapping.getProperty();        Object propertyValue = metaObject.getValue(propertyName);        if (propertyValue == null) {            Class<?> type = resultMapping.getJavaType();            if (type == null) {                type = metaObject.getSetterType(propertyName);            }            try {                if (objectFactory.isCollection(type)) {                    propertyValue = objectFactory.create(type);                    metaObject.setValue(propertyName, propertyValue);                    return propertyValue;                }            } catch (Exception e) {                throw new ExecutorException("Error instantiating collection property for result '"                        + resultMapping.getProperty() + "'.  Cause: " + e, e);            }        } else if (objectFactory.isCollection(propertyValue.getClass())) {            return propertyValue;        }        return null;    }    /**     * 调用结果处理器，将结果对象添加到结果处理器中     * @param resultHandler 结果处理器，     * @param resultContext 结果上下文     * @param rowValue 结果对象     */    private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue) {        // 设置下一个结果对象        resultContext.nextResultObject(rowValue);        /**         * 如果是DefaultResultHandler，就会将结果对象添加到内部的List对象中         * 如果是DefaultMapResultHandler，会将结果对象添加到内部的Map对象中         */        ((ResultHandler<Object>) resultHandler).handleResult(resultContext);    }    /**     * 据ResultMap中记录的Discriminator对象以及参与映射的记录行中相应的列值，决定映射使用的ResultMap对象。     *     * @param rs     * @param resultMap     * @param columnPrefix     * @return     * @throws SQLException     */    public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {        Set<String> pastDiscriminators = new HashSet<>();        // 其中包含了每个case对应的ResultMap        // discriminator中每个case解析成的ResultMap都包含了父ResultMap的所有ResultMapping        Discriminator discriminator = resultMap.getDiscriminator();        while (discriminator != null) {            // 获取当前行作为判断使用哪个case的列的值            final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);            // 从Discriminator中根据value的值来获取对应case解析成的ResultMap            final String discriminatedMapId = discriminator.getMapIdFor(String.valueOf(value));            if (configuration.hasResultMap(discriminatedMapId)) {                // 递归处理嵌套的discriminator                resultMap = configuration.getResultMap(discriminatedMapId);                Discriminator lastDiscriminator = discriminator;                discriminator = resultMap.getDiscriminator();                // 如果下一个discriminator和当前的是同一个，或者下一个discriminator已经遍历过，那么返回当前的resultMap                if (discriminator == lastDiscriminator || !pastDiscriminators.add(discriminatedMapId)) {                    break;                }            } else {                break;            }        }        return resultMap;    }    private Object getDiscriminatorValue(ResultSet rs, Discriminator discriminator, String columnPrefix)            throws SQLException {        final ResultMapping resultMapping = discriminator.getResultMapping();        final TypeHandler<?> typeHandler = resultMapping.getTypeHandler();        return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));    }    /**     * 获取第一个结果集     * @param stmt SQL脚本容器     * @return 结果集包装类对象     */    private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {        // 获取结果集        ResultSet resultSet = stmt.getResultSet();        // 如果结果集为null        while (resultSet == null) {            //前进得到第一个结果集以防 驱动不返回结果集 的第一个结果            /**             * getMoreResults:移动到Statement对象的下一个结果,如果下一个结果是ResultSet对象，返回true,             * 如果是一个更新记录数或者已经没有更多的结果时，返回false             */            if (stmt.getMoreResults()) {                // 获取结果集                resultSet = stmt.getResultSet();            } else {                //如果没有结果集                //getUpdateCount:更新记录数，没有时为-1                if (stmt.getUpdateCount() == -1) {                    /**                     * 当((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))                     * 就表示已经没有更多结果                     */                    break;                }            }        }        // 如果结果集不为null,就包装起来返回出去，否则 返回null        return resultSet != null ? new ResultSetWrapper(resultSet, configuration) : null;    }    @Override    public void handleOutputParameters(CallableStatement cs) throws SQLException {        //获取参数对象        final Object parameterObject = parameterHandler.getParameterObject();        //构建参数元对象        final MetaObject metaParam = configuration.newMetaObject(parameterObject);        //获取参数映射集合        final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();        //遍历参数映射集合        for (int i = 0; i < parameterMappings.size(); i++) {            //获取参数映射            final ParameterMapping parameterMapping = parameterMappings.get(i);            //如果参数映射的模式为输出参数 或者 参数映射的模式为输入/输出参数            if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {                //如果参数映射配置java类型是ResultSet                if (ResultSet.class.equals(parameterMapping.getJavaType())) {                    //处理结果游标的输出参数，将结果对象集合赋值到参数对象对应的属性中                    // handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);                } else {                    //获取类型处理器                    final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();                    //通过typeHandler获取指定列位置的结果对象，然后赋值到参数对象对应的属性中                    metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));                }            }        }    }    private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) {        return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();    }    /**     * 分页跳过指定的offset也     * 跳过rowBounds.offset记录数     * @param rs 结果集     * @param rowBounds Mybatis的分页对象     * @throws SQLException SQLException     */    private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {        if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {            if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {                // absolute:将指针移动到此 ResultSet 对象的给定行编号。                rs.absolute(rowBounds.getOffset());            }        } else {            // 通过ResultSet的next()改变rs的游标位置直到达到rowBounds设置的offset            for (int i = 0; i < rowBounds.getOffset(); i++) {                if (!rs.next()) {                    break;                }            }        }    }    /**     * 映射结果集到pojo上     * （1）createResultObject 生成对象     * （2）applyAutomaticMappings 自动映射     * （3）applyPropertyMappings property映射     *     * @param rsw     * @param resultMap     * @param columnPrefix     * @return     * @throws SQLException     */    private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {        // 延迟加载的映射信息        final ResultLoaderMap lazyLoader = new ResultLoaderMap();        // 创建要映射的PO类对象        Object rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);        // 结果对象不为空且类型处理器也不为空        if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {            final MetaObject metaObject = configuration.newMetaObject(rowValue);            boolean foundValues = this.useConstructorMappings;            // 是否应用自动映射，也就是通过resultType进行映射            if (shouldApplyAutomaticMappings(resultMap, false)) {                // 根据columnName和type属性名映射赋值                foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;            }            // 根据我们配置ResultMap的column和property映射赋值            // 如果映射存在nestedQueryId，会调用getNestedQueryMappingValue方法获取返回值            foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;            foundValues = lazyLoader.size() > 0 || foundValues;            rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;        }        return rowValue;    }    /**     * 对未能被映射列名映射关系集合进行尝试赋值，将结果集对应数据赋值到结果对象对应的属性中     * @param rsw 结果集包装类对象     * @param resultMap Mapper.xml的resultMap标签信息封装类对象     * @param metaObject 结果元对象     * @param columnPrefix 列名前缀     * @return 成功根据自动映射关系集合的元素构建出指定java类对象标记，返回true；否则返回false     */    private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {        //获取未能被映射列名映射关系集合        List<UnMappedColumnAutoMapping> autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);        //成功根据自动映射关系集合的元素构建出指定java类对象标记        boolean foundValues = false;        //如果自动映射关系集合不为空        if (!autoMapping.isEmpty()) {            //遍历自动映射关系集合            for (UnMappedColumnAutoMapping mapping : autoMapping) {                //从 ResultSet 中取出columnName对应数据，然后转换为 java 对象                final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);                //如果对象不为null                if (value != null) {                    //只要有一个成功根据自动映射关系集合的元素构建出指定java类对象，标记就会变成true                    foundValues = true;                }                /**                 * isCallSetterOnNulls:                 * 指定当结果集中值为 null 的时候是否调用映射对象的 setter（map 对象时为 put）方法，                 * 这在依赖于 Map.keySet() 或 null 值初始化的时候比较有用。                 * 注意基本类型（int、boolean 等）是不能设置成 null 的。                 */                //如果对象不为null,或者指定当结果集中值为null的时候允许调用映射对象的setter(map对象时为 put)方法,且不是基本类型                if (value != null || (configuration.isCallSettersOnNulls() && !mapping.primitive)) {                    // gcode issue #377, call setter on nulls (value is not 'found')                    //将value赋值到结果对象中的mapping.property属性中                    metaObject.setValue(mapping.property, value);                }            }        }        return foundValues;    }    private String prependPrefix(String columnName, String prefix) {        if (columnName == null || columnName.length() == 0 || prefix == null || prefix.length() == 0) {            return columnName;        }        return prefix + columnName;    }    /**     * 根据结果集和属性映射构建对应的目标对象，并赋值到结果对象中     * @param rsw 结果集包装类对象     * @param resultMap Mapper.xml的resultMap标签信息封装类对象     * @param metaObject 结果元对象     * @param lazyLoader 用来表示需要懒加载的属性集，本质是一个HashMap     * @param columnPrefix 列名前缀     * @return 成功根据结果集和属性映射构建对应的目标对象的标记，哪怕只有一个成功，都会为true     */    private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject,                                          ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {        //获取映射列名集合        final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);        //成功根据结果集和属性映射构建对应的目标对象的标记，哪怕只有一个成功，都会为true        boolean foundValues = false;        //获取属性映射关系集合，该集合不包括标记为构造函数的属性映射关系        final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();        //遍历属性映射关系        for (ResultMapping propertyMapping : propertyMappings) {            //拼接前缀与列名            String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);            //如果配置了嵌套的resultMapId            if (propertyMapping.getNestedResultMapId() != null) {                // the user added a column attribute to a nested result map, ignore it                //用户添加一个列属性是一个嵌套映射结果,忽略它;                column = null;            }            /**             *  如果属性映射存在组合ResultMaping列表             *  或者 column不为null且映射列名集合中包含column             *  或者 属性映射配置了用于加载复杂类型的结果集             */            if (propertyMapping.isCompositeResult()                    || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))                    || propertyMapping.getResultSet() != null) {                //根据结果集和属性映射构建对应的目标对象                Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);                // issue #541 make property optional                //获取属性映射的属性名                final String property = propertyMapping.getProperty();                //如果没有配置属性名                if (property == null) {                    //跳过该属性映射                    continue;                    //如果目标对象是一个标记为待定的对象                } else if (value == DEFERRED) {                    //成功根据结果集和属性映射构建对应的目标对象的标记设置为true                    foundValues = true;                    continue;                }                //如果目标对象不为null                if (value != null) {                    //成功根据结果集和属性映射构建对应的目标对象的标记设置为true                    foundValues = true;                }                /**                 * isCallSetterOnNulls:                 * 指定当结果集中值为 null 的时候是否调用映射对象的 setter（map 对象时为 put）方法，                 * 这在依赖于 Map.keySet() 或 null 值初始化的时候比较有用。                 * 注意基本类型（int、boolean 等）是不能设置成 null 的。                 */                //如果对象不为null,或者指定当结果集中值为null的时候允许调用映射对象的setter(map对象时为 put)方法,且不是基本类型                if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) {                    // gcode issue #377, call setter on nulls (value is not 'found')                    //将value赋值到结果对象中的mapping.property属性中                    metaObject.setValue(property, value);                }            }        }        return foundValues;    }    /**     * 根据结果集和属性映射对应的目标对象     * @param rs 结果集     * @param metaResultObject 结果元对象     * @param propertyMapping 属性映射     * @param lazyLoader 用来表示需要懒加载的属性集，本质是一个HashMap     * @param columnPrefix 列名前缀     * @return 根据结果集和属性映射构建对应的目标对象     */    private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)            throws SQLException {        //如果属性映射配置了嵌套select标签Id        if (propertyMapping.getNestedQueryId() != null) {            //构建带有嵌套查询属性的值对象            return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);            //如果加载复杂类型的结果集        } else if (propertyMapping.getResultSet() != null) {            // 添加 {propertyMapping待定关系到待定关系映射集合 {@link #pendingRelations}            addPendingChildRelation(rs, metaResultObject, propertyMapping);   // TODO is that OK?            //返回标记着待定的对象            return DEFERRED;        } else {            //属性映射的默认情况处理            //获取属性映射的TypeHandler            final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();            //获取属性映射的列名，并拼接列名前缀            final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);            //从 ResultSet 中取出columnName对应数据，然后转换为 java 对象            return typeHandler.getResult(rs, column);        }    }    /**     * 添加 {@code parentMapping} 待定关系到待定关系映射集合 {@link #pendingRelations}     * @param rs 结果集对象     * @param metaResultObject 结果元对象     * @param parentMapping 父级属性映射     */    private void addPendingChildRelation(ResultSet rs, MetaObject metaResultObject, ResultMapping parentMapping) throws SQLException {        //为多个结果数据创建缓存Key        CacheKey cacheKey = createKeyForMultipleResults(rs, parentMapping, parentMapping.getColumn(), parentMapping.getColumn());        //创建一个待定关系类对象        PendingRelation deferLoad = new PendingRelation();        //将结果元对象赋值到待定关系类对象中        deferLoad.metaObject = metaResultObject;        //将父级属性映射赋值到待定关系类对象中        deferLoad.propertyMapping = parentMapping;        //从待定关系映射集合中获取cacheKey对应的待定关系集合，如果没有对应的待定关系集合会新建一个集合返回出去。        List<PendingRelation> relations = pendingRelations.computeIfAbsent(cacheKey, k -> new ArrayList<>());        // issue #255        //添加待定关系到集合中        relations.add(deferLoad);        //从之前整合的结果映射对象映射集合中获取parentMapping.getResultSet()配置对应结果映射        ResultMapping previous = nextResultMaps.get(parentMapping.getResultSet());        //如果没有找对应的结果映射        if (previous == null) {            //将结果映射加入到之前整合的结果映射对象映射集合中            nextResultMaps.put(parentMapping.getResultSet(), parentMapping);        } else {            //如果获取出来的映射结果和paraentMapping不是同一对象            if (!previous.equals(parentMapping)) {                //两个不同的属性不可以映射到相同的结果集                throw new ExecutorException("Two different properties are mapped to the same resultSet");            }        }    }    /**     * 为多个结果数据创建缓存Key     * @param rs 结果集     * @param resultMapping 结果属性映射     * @param names 列名     * @param columns 列名     * @return 对应多个结果数据缓存Key     */    private CacheKey createKeyForMultipleResults(ResultSet rs, ResultMapping resultMapping, String names, String columns) throws SQLException {        //新建一个缓存Key对象        CacheKey cacheKey = new CacheKey();        //将结果属性映射作为缓存Key的一部分的        cacheKey.update(resultMapping);        //如果两个列名参数都不为null        if (columns != null && names != null) {            //因为有可能指代多个列名，所以用逗号进行分割            String[] columnsArray = columns.split(",");            ///因为有可能指代多个列名，所以用逗号进行分割            String[] namesArray = names.split(",");            //遍历列名数组            for (int i = 0; i < columnsArray.length; i++) {                //获取列名对应结果数据                Object value = rs.getString(columnsArray[i]);                if (value != null) {                    //将列名映射作为缓存Key的一部分的                    cacheKey.update(namesArray[i]);                    //将列名对应结果数据作为缓存Key的一部分的                    cacheKey.update(value);                }            }        }        return cacheKey;    }    private Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping,                                              ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {        final String nestedQueryId = propertyMapping.getNestedQueryId();        final String property = propertyMapping.getProperty();        final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);        final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();        final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping,                nestedQueryParameterType, columnPrefix);        Object value = null;        if (nestedQueryParameterObject != null) {            final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);            final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT,                    nestedBoundSql);            final Class<?> targetType = propertyMapping.getJavaType();            if (executor.isCached(nestedQuery, key)) {                executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType);                value = DEFERRED;            } else {                final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery,                        nestedQueryParameterObject, targetType, key, nestedBoundSql);                if (propertyMapping.isLazy()) {                    lazyLoader.addLoader(property, metaResultObject, resultLoader);                    value = DEFERRED;                } else {                    value = resultLoader.loadResult();                }            }        }        return value;    }    private Object prepareParameterForNestedQuery(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType,                                                  String columnPrefix) throws SQLException {        if (resultMapping.isCompositeResult()) {            return prepareCompositeKeyParameter(rs, resultMapping, parameterType, columnPrefix);        } else {            return prepareSimpleKeyParameter(rs, resultMapping, parameterType, columnPrefix);        }    }    private Object prepareSimpleKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType,                                             String columnPrefix) throws SQLException {        final TypeHandler<?> typeHandler;        if (typeHandlerRegistry.hasTypeHandler(parameterType)) {            typeHandler = typeHandlerRegistry.getTypeHandler(parameterType);        } else {            typeHandler = typeHandlerRegistry.getUnknownTypeHandler();        }        return typeHandler.getResult(rs, prependPrefix(resultMapping.getColumn(), columnPrefix));    }    private Object prepareCompositeKeyParameter(ResultSet rs, ResultMapping resultMapping, Class<?> parameterType,                                                String columnPrefix) throws SQLException {        final Object parameterObject = instantiateParameterObject(parameterType);        final MetaObject metaObject = configuration.newMetaObject(parameterObject);        boolean foundValues = false;        for (ResultMapping innerResultMapping : resultMapping.getComposites()) {            final Class<?> propType = metaObject.getSetterType(innerResultMapping.getProperty());            final TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(propType);            final Object propValue = typeHandler.getResult(rs,                    prependPrefix(innerResultMapping.getColumn(), columnPrefix));            // issue #353 & #560 do not execute nested query if key is null            if (propValue != null) {                metaObject.setValue(innerResultMapping.getProperty(), propValue);                foundValues = true;            }        }        return foundValues ? parameterObject : null;    }    private Object instantiateParameterObject(Class<?> parameterType) {        if (parameterType == null) {            return new HashMap<>();        } else if (MapperMethod.ParamMap.class.equals(parameterType)) {            return new HashMap<>(); // issue #649        } else {            return objectFactory.create(parameterType);        }    }    /**     * 是否可以应用自动映射     * @param resultMap Mapper.xml的resultMap标签信息封装类对象     * @param isNested 是否是嵌套的     * @return 可以应用自动映射，返回true；否则返回false     */    private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {        //如果配置了自动映射标记        if (resultMap.getAutoMapping() != null) {            //自动映射            return resultMap.getAutoMapping();        } else {            //如果是嵌套            if (isNested) {                //AutoMappingBehavior.FULL表示： 自动映射任意复杂的结果集（无论是否嵌套）。                return AutoMappingBehavior.FULL == configuration.getAutoMappingBehavior();            } else {                //AutoMappingBehavior.NODE：取消自动映射                //AutoMappingBehavior.PARTIAL：自动映射没有定义嵌套结果集映射的结果集                return AutoMappingBehavior.NONE != configuration.getAutoMappingBehavior();            }        }    }    /**     * 获取未能被映射列名映射关系集合     * @param rsw 结果集包装类对象     * @param resultMap Mapper.xml的resultMap标签信息封装类对象     * @param metaObject 结果元对象     * @param columnPrefix 列名     * @return 未能被映射列名映射关系集合     * @throws SQLException     */    private List<UnMappedColumnAutoMapping> createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {        //构建autoMappingCache的Key        final String mapKey = resultMap.getId() + ":" + columnPrefix;        //获取mapKey的自动映射集合        List<UnMappedColumnAutoMapping> autoMapping = autoMappingsCache.get(mapKey);        //如果自动映射集合为null        if (autoMapping == null) {            //初始化自动映射集合            autoMapping = new ArrayList<>();            //获取未被映射的列名集合            final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);            //遍历未被映射的列名集合            for (String columnName : unmappedColumnNames) {                //将列名当作属性名                String propertyName = columnName;                //如果列名前缀不为null且不是空字符串                if (columnPrefix != null && !columnPrefix.isEmpty()) {                    // When columnPrefix is specified,                    // ignore columns without the prefix.                    //当列名前缀被指定了，就忽略没有指定前缀的列                    //列名是以columnPrefix开头                    if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {                        //去掉columnPrefix赋值给propertyName                        propertyName = columnName.substring(columnPrefix.length());                    } else {                        //忽略没有指定前缀的列                        continue;                    }                }                /**                 * isMapUnderscoreToCamelCase：是否开启自动驼峰命名规则（camel case）映射，                 * 即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射                 */                //查看结果对象是否存在propertyName属性,存在便会返回该属性名                final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());                //如果属性不为null且结果对象有这个属性的setter方法                if (property != null && metaObject.hasSetter(property)) {                    //如果配置的映射属性名中有这个属性                    if (resultMap.getMappedProperties().contains(property)) {                        //跳过                        continue;                    }                    //获取结果对象的property的setter方法的参数类型                    final Class<?> propertyType = metaObject.getSetterType(property);                    //如果存在propertyType和columnName的jdbcType的TypeHandler                    if (typeHandlerRegistry.hasTypeHandler(propertyType, rsw.getJdbcType(columnName))) {                        //获取propertyType和columnName的TypeHandler                        final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);                        //构建UnMappedColumnAutoMapping对象，并添加到autoMapping中                        autoMapping.add(new UnMappedColumnAutoMapping(columnName, property, typeHandler, propertyType.isPrimitive()));                    } else {                        //不存在propertyType和columnName的jdbcType的TypeHandler时                        /**                         * AutoMappingUnknownColumnBehavior: 指定发现自动映射目标未知列（或者未知属性类型）的行为                         * NONE:不做任何反应,默认                         * WARNING:输出提醒日志                         * FAILING:映射失败 (抛出 SqlSessionException)                         */                        //AutoMappingUnknownColumnBehavior为枚举类，doAction为枚举方法。                        /**                         * 根据配置的AutoMappingUnknownColumnBehavior枚举类，作出相应的处理，要么什么都不做，要                         * 么输出提醒日志，要么抛出SqlSessionException                         */                        configuration.getAutoMappingUnknownColumnBehavior()                                .doAction(mappedStatement, columnName, property, propertyType);                    }                } else {                    //属性为null或者结果对象没有这个属性的setter方法                    /**                     * 根据配置的AutoMappingUnknownColumnBehavior枚举类，作出相应的处理，要么什么都不做，要                     * 么输出提醒日志，要么抛出SqlSessionException                     */                    configuration.getAutoMappingUnknownColumnBehavior()                            .doAction(mappedStatement, columnName, (property != null) ? property : propertyName, null);                }            }            //保存结果对象的自动自动映射集合            autoMappingsCache.put(mapKey, autoMapping);        }        return autoMapping;    }    private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader,                                      String columnPrefix) throws SQLException {        this.useConstructorMappings = false; // reset previous mapping result        final List<Class<?>> constructorArgTypes = new ArrayList<>();        final List<Object> constructorArgs = new ArrayList<>();        // 创建结果映射的PO类对象        Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);        if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {            // 获取要映射的PO类的属性信息            final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();            for (ResultMapping propertyMapping : propertyMappings) {                // issue gcode #109 && issue #149                // 延迟加载处理                if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {                    // 通过动态代理工厂，创建延迟加载的代理对象                    resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration,                            objectFactory, constructorArgTypes, constructorArgs);                    break;                }            }        }        this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping        // result        return resultObject;    }    /**     * 取得构造函数所需的参数值去创建结果对象     * @param rsw 结果集包装类对象     * @param resultMap Mapper.xml的resultMap标签信息封装类对象     * @param constructorArgTypes 构造函数参数类型集合     * @param constructorArgs 构造函数参数集合     * @param columnPrefix 列名前缀     * @return {@link ResultMap#getType()} 类型的对象     */    private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes,                                      List<Object> constructorArgs, String columnPrefix) throws SQLException {        // 获取结果对象类型        final Class<?> resultType = resultMap.getType();        // 构建结果对象类型的元对象        final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);        // 获取构造函数映射关系        final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();        // 如果存在对应的TypeHandler        if (hasTypeHandlerForResultObject(rsw, resultType)) {            // 创建原始的结果对象            return createPrimitiveResultObject(rsw, resultMap, columnPrefix);            // 构造函数映射关系不为空        } else if (!constructorMappings.isEmpty()) {            // 根据构造函数映射构建的结果对象            return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);            // 如果resultType是接口或者resultType有默认的构造函数        } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {            // 让objectFactory创建通过默认构造函数resultType对象            return objectFactory.create(resultType);            // 是否可以应用自动映射        } else if (shouldApplyAutomaticMappings(resultMap, false)) {            // 取得构造函数所需的参数值去创建结果对象(自动映射)            return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix);        }        throw new ExecutorException("Do not know how to create an instance of " + resultType);    }    private Object createPrimitiveResultObject(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix)            throws SQLException {        final Class<?> resultType = resultMap.getType();        final String columnName;        if (!resultMap.getResultMappings().isEmpty()) {            final List<ResultMapping> resultMappingList = resultMap.getResultMappings();            final ResultMapping mapping = resultMappingList.get(0);            columnName = prependPrefix(mapping.getColumn(), columnPrefix);        } else {            columnName = rsw.getColumnNames().get(0);        }        final TypeHandler<?> typeHandler = rsw.getTypeHandler(resultType, columnName);        return typeHandler.getResult(rsw.getResultSet(), columnName);    }    Object createParameterizedResultObject(ResultSetWrapper rsw, Class<?> resultType,                                           List<ResultMapping> constructorMappings, List<Class<?>> constructorArgTypes, List<Object> constructorArgs,                                           String columnPrefix) {        //有构建出构造函数参数对象的标记        boolean foundValues = false;        //遍历构造函数参数映射关系        for (ResultMapping constructorMapping : constructorMappings) {            //获取构造函数参数映射关系对应java类型            final Class<?> parameterType = constructorMapping.getJavaType();            //获取构造函数参数映射关系对应的列名            final String column = constructorMapping.getColumn();            final Object value;            try {                if (constructorMapping.getNestedQueryId() != null) {                    value = getNestedQueryConstructorValue(rsw.getResultSet(), constructorMapping, columnPrefix);                } else if (constructorMapping.getNestedResultMapId() != null) {                    final ResultMap resultMap = configuration.getResultMap(constructorMapping.getNestedResultMapId());                    value = getRowValue(rsw, resultMap, constructorMapping.getColumnPrefix());                } else {                    final TypeHandler<?> typeHandler = constructorMapping.getTypeHandler();                    value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(column, columnPrefix));                }            } catch (ResultMapException | SQLException e) {                throw new ExecutorException("Could not process result for mapping: " + constructorMapping, e);            }            constructorArgTypes.add(parameterType);            constructorArgs.add(value);            foundValues = value != null || foundValues;        }        return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;    }    private Object getNestedQueryConstructorValue(ResultSet rs, ResultMapping constructorMapping, String columnPrefix)            throws SQLException {        final String nestedQueryId = constructorMapping.getNestedQueryId();        final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);        final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();        final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, constructorMapping,                nestedQueryParameterType, columnPrefix);        Object value = null;        if (nestedQueryParameterObject != null) {            final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);            final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT,                    nestedBoundSql);            final Class<?> targetType = constructorMapping.getJavaType();            final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery,                    nestedQueryParameterObject, targetType, key, nestedBoundSql);            value = resultLoader.loadResult();        }        return value;    }    private Object createByConstructorSignature(ResultSetWrapper rsw, Class<?> resultType,                                                List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix) throws SQLException {        final Constructor<?>[] constructors = resultType.getDeclaredConstructors();        final Constructor<?> defaultConstructor = findDefaultConstructor(constructors);        if (defaultConstructor != null) {            return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix,                    defaultConstructor);        } else {            for (Constructor<?> constructor : constructors) {                if (allowedConstructorUsingTypeHandlers(constructor, rsw.getJdbcTypes())) {                    return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix,                            constructor);                }            }        }        throw new ExecutorException(                "No constructor found in " + resultType.getName() + " matching " + rsw.getClassNames());    }    private boolean allowedConstructorUsingTypeHandlers(final Constructor<?> constructor,                                                        final List<JdbcType> jdbcTypes) {        final Class<?>[] parameterTypes = constructor.getParameterTypes();        if (parameterTypes.length != jdbcTypes.size())            return false;        for (int i = 0; i < parameterTypes.length; i++) {            if (!typeHandlerRegistry.hasTypeHandler(parameterTypes[i], jdbcTypes.get(i))) {                return false;            }        }        return true;    }    private Constructor<?> findDefaultConstructor(final Constructor<?>[] constructors) {        if (constructors.length == 1)            return constructors[0];        for (final Constructor<?> constructor : constructors) {            if (constructor.isAnnotationPresent(AutomapConstructor.class)) {                return constructor;            }        }        return null;    }    private Object createUsingConstructor(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes,                                          List<Object> constructorArgs, String columnPrefix, Constructor<?> constructor) throws SQLException {        boolean foundValues = false;        for (int i = 0; i < constructor.getParameterTypes().length; i++) {            Class<?> parameterType = constructor.getParameterTypes()[i];            String columnName = rsw.getColumnNames().get(i);            TypeHandler<?> typeHandler = rsw.getTypeHandler(parameterType, columnName);            Object value = typeHandler.getResult(rsw.getResultSet(), prependPrefix(columnName, columnPrefix));            constructorArgTypes.add(parameterType);            constructorArgs.add(value);            foundValues = value != null || foundValues;        }        return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;    }    private void validateResultMapsCount(ResultSetWrapper rsw, int resultMapCount) {        if (rsw != null && resultMapCount < 1) {            throw new ExecutorException(                    "A query was run and no Result Maps were found for the Mapped Statement '" + mappedStatement.getId()                            + "'.  It's likely that neither a Result Type nor a Result Map was specified.");        }    }    private void ensureNoRowBounds() {        if (configuration.isSafeRowBoundsEnabled() && rowBounds != null                && (rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT || rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET)) {            throw new ExecutorException(                    "Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. "                            + "Use safeRowBoundsEnabled=false setting to bypass this check.");        }    }    protected void checkResultHandler() {        if (resultHandler != null && configuration.isSafeResultHandlerEnabled() && !mappedStatement.isResultOrdered()) {            throw new ExecutorException(                    "Mapped Statements with nested result mappings cannot be safely used with a custom ResultHandler. "                            + "Use safeResultHandlerEnabled=false setting to bypass this check "                            + "or ensure your statement returns ordered data and set resultOrdered=true on it.");        }    }    /**     * 别名来判断是否存在该pojo对象     *     * @param rsw     * @param resultType     * @return     */    private boolean hasTypeHandlerForResultObject(ResultSetWrapper rsw, Class<?> resultType) {        if (rsw.getColumnNames().size() == 1) {            return typeHandlerRegistry.hasTypeHandler(resultType, rsw.getJdbcType(rsw.getColumnNames().get(0)));        }        return typeHandlerRegistry.hasTypeHandler(resultType);    }}